package com.common.help.test10;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class Test {
	
	private static Class c;
	private static Person person = new Person();
	private static String className = "com.common.help.test10.Person";
	
	public static void main(String[] args) throws Exception {
			createClass();
			createInstance(c);
			getConstructs(c);
			getMethods(c);
			GetFields(c);
			getClassOtherInfo(c);
			callConstruct(c);
			callMethod(c);
			callField(c);
	}
    
	
	public static void createClass() throws Exception{
		//方法一 : 调用运行时类的.class属性
	    c = Person.class;
	    System.out.println("方法一 : 调用运行时类的.class属性: "+c.toString());

	    //方法二 : 通过运行时类的对象，调用getClass()方法
	    //c = person.getClass();
	    //System.out.println("方法二 : 通过运行时类的对象，调用getClass()方法: "+c.toString());

	    //方法三 : 调用Class的静态方法forName(String className)
	    c = Class.forName(Person.class.getName().toString());
	    //c = Class.forName(className);
	    System.out.println("方法三 : 调用Class的静态方法forName(String className): "+c.toString());


	    //方法四：通过类的加载器
//	      ClassLoader classLoader = this.getClass().getClassLoader();
	    ClassLoader classLoader = Person.class.getClassLoader();
	    c = classLoader.loadClass(className);
	    System.out.println("方法四：通过类的加载器: "+c.toString());
	}
	
	public static void createInstance(Class c) throws Exception {
	    //方法一：调用Class的newInstance方法创建运行时类的对象
	    System.out.println(" ");
	    System.out.println("createInstance()");
	    person = (Person)c.newInstance();       
	    System.out.println("方法一：调用Class的newInstance方法创建运行时类的对象  --person: "+person);
	    
	    System.out.println(" ");
	    System.out.println("createInstance()");
	    Constructor constructor = c.getDeclaredConstructor(String.class,int.class,int.class);
	    person = (Person)constructor.newInstance("hh",1,1);
	    System.out.println("方法二：调用指定的构造器(public)创建运行时类的对象 --person: "+person);
	    
	    System.out.println(" ");
	    System.out.println("createInstance()");
	    constructor = c.getDeclaredConstructor(String.class);
	    constructor.setAccessible(true);
	    person = (Person)constructor.newInstance("hh");
	    System.out.println("方法二：调用指定的构造器(private)创建运行时类的对象 --person: "+person);
	}
	private static void getConstructs(Class c) {
		
	
		//public的构造方法
		Constructor[] constructors = c.getConstructors();
	
		for(Constructor constructor : constructors){
			System.out.println(constructor);
		}
		Constructor[] constructors1 = c.getDeclaredConstructors();
		for(Constructor constructor1 : constructors1){
			System.out.println(constructor1);
		}
	
	}
	
	private static void getMethods(Class c) {
	    System.out.println(" ");
	    System.out.println("getMethods");
	    //getMethods 此方法为获取类的public方法，包括父类的public方法
	    System.out.println("getMethods  此方法为获取类的public方法，包括父类的public方法 ");
		Method[] methods = c.getMethods();
		for(Method method : methods){
			System.out.println(method);
		}
		System.out.println(" ");
	    System.out.println("getDeclaredMethods  此方法为获取类本身声明的所有方法，包括private ");
		Method[] declareMethods = c.getDeclaredMethods();
		for(Method method : declareMethods){
			System.out.println(method);
		}
		
	}
	private static void GetFields(Class c) {
	    // TODO Auto-generated method stub
	    System.out.println(" ");
	    System.out.println("GetFields");
	    //getFields 此方法为获取类的public属性，包括父类的public属性
	    System.out.println("getFields 此方法为获取类的public属性，包括父类的public属性 ");
	    Field[] field1 = c.getFields();     
	    for(int i=0;i<field1.length;i++){
	        System.out.println("field1 ["+i+"] :"+field1[i]);
	    }

	    System.out.println(" ");
	    //getDeclaredFields 此方法为获取类的本身声明的所有属性，包括private
	    System.out.println("getDeclaredFields 此方法为获取类的本身声明的所有属性，包括private ");
	    Field[] field2 = c.getDeclaredFields();     
	    for(int i=0;i<field2.length;i++){
	        System.out.println("field2 ["+i+"] :"+field2[i]);
	    }
	}
	//获取类的其它信息，如包，父类，接口，内部类等等
	private static void getClassOtherInfo(Class c) {
	    // TODO Auto-generated method stub
	    System.out.println(" ");
	    System.out.println("getClassOtherInfo");
	    //获取类的包
	    String p = c.getPackage().toString();
	    System.out.println("类的包名："+p);
	    //获取类的父类
	    Class parentClass = c.getSuperclass();
	    System.out.println("类的父类："+parentClass.getName());

	    //获取类的接口
	    Class[] interfaces =c.getInterfaces();
	    if(interfaces.length >0){
	        System.out.println("类的接口：");
	        for(int i=0;i<interfaces.length;i++){               
	            System.out.println("interfaces["+i+"] :"+interfaces[i]);
	        }
	    }

	    //获取类的内部类
	    //getDeclaredClasses方法获取类本身定义的所有内部类，包括private
	    Class[] innerClass1 =c.getDeclaredClasses();
	    if(innerClass1.length >0){
	        System.out.println("类的所有内部类 ，包括private：");
	        for(int i=0;i<innerClass1.length;i++){              
	            System.out.println("innerClass1["+i+"] :"+innerClass1[i]);
	        }
	    }

	    //同理getClasses方法获取类的public内部类，包括父类的public内部类
	    Class[] innerClass2 =c.getClasses();
	    if(innerClass2.length >0){
	        System.out.println("类的public内部类，包括父类的public内部类：");
	        for(int i=0;i<innerClass2.length;i++){              
	            System.out.println("innerClass2["+i+"] :"+innerClass2[i]);
	        }
	    }
	}
	//2.3.1 对指定构造方法进行操作
	private static void callConstruct(Class c) throws Exception {
	    // TODO Auto-generated method stub
	    System.out.println(" ");
	    System.out.println("callConstruct");

	    //对private类型的构造方法进行操作
	    Constructor constructor1 = c.getDeclaredConstructor(String.class);
	    constructor1.setAccessible(true);
	    person = (Person)constructor1.newInstance("zsmj");
	    System.out.println("person:"+person);

	    //对public类型的构造方法进行操作
	    Constructor constructor2 = c.getDeclaredConstructor(String.class,int.class,int.class);
	    //constructor2.setAccessible(true);
	    person = (Person)constructor2.newInstance("yyf",10,2);
	    System.out.println("person:"+person);
	}
	
	
	//2.3.2 对指定方法进行操作
	private static void callMethod(Class c) throws Exception {
	    System.out.println(" ");
	    System.out.println("callMethod");

		//1.对private类型的方法进行操作
	    //getDeclaredMethod 方法获取类本身声明的方法，包括private类型的方法
	    System.out.println("getDeclaredMethod 方法获取类本身声明的方法，包括private类型的方法，以setName方法为例:");
	    Method method = c.getDeclaredMethod("setName", String.class);
	    //private类型的方法
	    System.out.println("修改前的person:"+person);
	    method.setAccessible(true);
	    method.invoke(person, "Zsmj");
	    System.out.println("修改后的person:"+person);
	    
	    //2.对public类型的方法进行操作，包括父类的方法
	    //getMethod 对public类型的方法进行操作，包括父类的方法
	    //2.1 以运行类的本身声明的public类型的setAge方法为例
	    System.out.println("getMethod 对public类型的方法进行操作，包括父类的方法,以类本身的setAge方法为例:");
	    Method method1 = c.getMethod("setAge", int.class);
	    System.out.println("修改前的person:"+person);
	    method1.setAccessible(true);
	    method1.invoke(person, 11);
	    System.out.println("修改后的person:"+person);
	    
	    //2.对public类型的方法进行操作，包括父类的方法
	    System.out.println("getMethod 对public类型的方法进行操作，包括父类的方法,以类本身的setWeight方法为例:");
	    Method method2 = c.getMethod("setWeight", int.class);
	    System.out.println("修改前的person:"+person);
	    method2.setAccessible(true);
	    method2.invoke(person, 110);
	    System.out.println("修改后的person:"+person);
	    
	    //3.对static类型的方法进行操作，以类本身的showWeather静态方法为例
	    System.out.println("getMethod 对public类型的方法进行操作，包括父类的方法,以父类的showWeather方法为例:");
	    Method m4 = c.getMethod("showWeather");
	    m4.invoke(null);
	    
	    
	    //4 获取指定方法的返回值,以类本身的private类型的getName方法为例
	    System.out.println("获取指定方法的返回值,以类本身的private类型的getName方法为例:");
	    Method m5 = c.getDeclaredMethod("getName");
	    m5.setAccessible(true);
	    String name = (String)m5.invoke(person);
	    System.out.println("name:"+name);
	}
	
	//2.3.3 对指定属性进行操作
	private static void callField(Class c) throws Exception {
	    // TODO Auto-generated method stub
	    System.out.println(" ");
	    System.out.println("callField");

	    //1.对public类型的属性进行操作，以类本身的public属性id为例:
	    System.out.println("对public类型的属性进行操作，以类本身的public属性id为例");
	    Field f1 = c.getField("id");
	    int id = (int)f1.get(person);
	    System.out.println("修改前person对象的id="+id);
	    f1.set(person, 3);
	    id = (int)f1.get(person);
	    System.out.println("修改后person对象的id="+id);
	    
	    //2.对private类型的属性进行操作，以类本身的private属性age为例:
	    System.out.println("对private类型的属性进行操作，以类本身的private属性age为例:");
	    Field f2 = c.getDeclaredField("age");
	    f2.setAccessible(true);
	    int age = (int)f2.get(person);
	    System.out.println("修改前person对象的age="+age);
	    f2.set(person, 12);
	    age = (int)f2.get(person);
	    System.out.println("修改后person对象的age="+age);
	    
	    //3.对static类型的属性进行操作，以类本身的static属性weather为例:
	    System.out.println("对static类型的属性进行操作，以类本身的static属性weather为例:");
	    Field f3 = c.getDeclaredField("weather");
	    f3.setAccessible(true);
	    String weather = (String)f3.get(person);
	    System.out.println("修改前person对象的weather="+weather);
	    f3.set(null, "台风来了~~~~");
	    weather = (String)f3.get(person);
	    System.out.println("修改后person对象的weather="+weather);
	    
	    
	    
	}
}